import { action, observable, computed, toJS } from "mobx";
import { each, set, uniqBy } from 'lodash';
import * as API from "../../apis/excelsearch";
import ListAPI from '../../apis';
import { message } from "antd";
import FieldCellType, { FieldTypeName, getInputValue } from "./excel/celltypes/FieldCellType";
import { register } from "./excel/command";
import HeaderCellType from "./excel/celltypes/HeaderCellType";
import { getTextLength, getRealLength, getFloatQfws } from "./excel/util";
import { judgeValueIsInt, judgeValueIsNumber } from "../../util/modeUtil";
import { saveDatas } from "../../apis/batchAdd";
import $ from 'jquery';
import { Modal } from "antd";
import { WeaLocaleProvider } from 'ecCom';
import listStore from "./index"
const getLabel = WeaLocaleProvider.getLabel;
import window, { replaceE8Url } from '../../util';
import _ from 'lodash';
import { showExpendError } from "../../util/cubeUtil";
import { modeList } from "../../util/searchUtil";
export interface IColumns {
    id: string;
    column: string;
    colwidth: string;
    editable: string;
    text: string;
    typeName: FieldTypeName;
    options?: any[];
    type?: string;
    dbtype?: string;
    isSingle?: string;

    length: number;
    qfws: number;
    width?: number;
    title?: string;
    asynLoadAll?: string;
    defaultExpandedLevel?: string;
    dataParams?: {};
    destDataParams?: {};
    conditionDataParams?: {};
    tabs?: any;
    hasAdvanceSerach?: boolean;
    scrollx?: boolean;
}
export enum FieldHtmlType {
    Input = '1',
    Textarea = '2',
    Browser = '3',
    Check = '4',
    Select = '5',
    Upload = '6',
    Null = ''
}
export interface IFieldEditableProps {
    colwidth: string;
    editable: string;
    fieldhtmltype: FieldHtmlType;
    fieldid: string;
    fieldlabel: string;
    fieldname: string;
    qfws: number;
    type: string;
    viewtype: string;

}
export interface IColumnsResult {
    allWidth: number;
    avgwidth: number;
    resultList: IColumns[];
    status: string;
    siderWidth: number;
}
export interface IVerifyFieldResult {
    status: '1' | '0';
    VerifyField: any[];
}
export interface IDataResult {
    datas: any[];
}
export interface IRowHeight {
    randomFieldId: string;
    randomFieldSubKeyd_id: string;
    height: number;
}
export interface color {
    randomFieldId: string;
    fieldid: string;
    color: string;
    fieldname: string;
}
let flag1 = false;//批量修改保存按钮状态，多次点击保存按钮，只会发送一次请求

const getRandomFieldId = (key) => {
    const [randomFieldId, randomFieldSubKeyd_id = ''] = key.split('^^--^^');
    return {
        randomFieldId,
        randomFieldSubKeyd_id
    };
}
export const getRandomId = (data) => {
    return data.randomFieldSubKeyd_id ? `${data.randomFieldId}^^--^^${data.randomFieldSubKeyd_id}` : data.randomFieldId;
}



export const StoreFuncs: {
    getRandomId: (row: number) => string;
    changeValue: (info: GC.Spread.Sheets.IValueChangedEventArgs) => void;
    getInstance: () => ExcelStore;
} = {} as any;
export default class ExcelStore {
    params: any;
    workbook: GC.Spread.Sheets.Workbook;
    dataSource: GC.Spread.Sheets.Bindings.CellBindingSource;
    table: GC.Spread.Sheets.Tables.Table;
    columns: GC.Spread.Sheets.Tables.TableColumn[] = [];
    contextMenu: GC.Spread.Sheets.ContextMenu.ContextMenu;
    @observable editable = false;
    backColumn: IColumns[];
    @observable loading = false;
    @observable dataKey: string;
    @observable current: number = 1;
    @observable hasMore = true;
    pageSize: number = 10;
    oldInfo = "";
    clearInfoTimer: number;
    datas: any[] = [];
    @observable browserMap = {};
    changedValues: any = {};
    initWorkbook?: Function;
    topRow: number = 0;
    leftCol: number = 0;
    rowHeights: any = {};
    insertedRows: string[] = [];
    siderWidth: number = 70;
    newDatas: string[] = [];
    @observable filterVisible = false;
    @observable sortKey;
    parm: any = {};
    @observable rightMenus = [] as any[];
    @observable billIds = [] as any[];
    @observable sort;
    @observable colorData = [] as any;
    keyIndex: any = {};
    nameIndex: any = {};
    colortime: string;
    @observable data: IDataResult;
    @observable opentype:string = ''; // 打开链接方式
    @observable lockrow: string = '-1'; //锁定行
    @observable lockcol: string = '-1'; //锁定列
    deleteDatas: string[] = [];
    constructor(params) {
        this.params = params;
        StoreFuncs.changeValue = (info: GC.Spread.Sheets.IValueChangedEventArgs) => {
            this.valueChanged('', info)
        };
        StoreFuncs.getInstance = () => this;
        StoreFuncs.getRandomId = (row: number) => {
            const { row: startRow } = this.table.dataRange();
            const data = this.dataSource.getValue(`datas.${row - startRow}`);
            return getRandomId(data);
        }
        (window as any).cubeOpenHreflinkFromExcel = (hreflink) => {
            const { opentype } = this;
            if (hreflink.indexOf('opentype=0') > -1 || opentype === '0') {
                (window as any).modeopenFullWindowHaveBar(hreflink);
            } else if (hreflink.indexOf('opentype=1') > -1 || opentype === '1') {
                (window as any).cubeOpenFullWindowBySelf(hreflink);
            } else if (hreflink.indexOf('opentype=2') > -1 || opentype === '2') {
                (window as any).openSlideModal(true, hreflink, this.siderWidth);
            } else {
                window.open(hreflink);
            }
        }
        this.bingDatas = this.bingDatas.bind(this)
    }

    @computed get selectedRowKeys(): string[] {
        if (this.workbook && this.dataSource) {
            const selections = this.workbook.getActiveSheet().getSelections();
            const rows: number[] = [];
            const { row: dataRow } = this.table.dataRange();
            selections.forEach(({ row, rowCount }) => {
                for (let index = 0; index < rowCount; index++) {
                    rows.push(row + index - dataRow);
                }
            });
            const datas = this.dataSource.getValue('datas');
            return rows.filter(row => row > -1).map(row => {
                return datas[row] ? datas[row].randomFieldId as string : '';
            })
        } else {
            return [];
        }
    }
    set selectedRowKeys(selectedRowKeys: string[]) {

    }


    // 点击排序
    @action
    cilckSort = (orderkey) => {

        this.filterVisible = false;
        let sort = 'ascend';
        if (this.sortKey) {

            const sorts = this.sortKey.split("@");
            if (sorts[0] == orderkey) {
                sort = sorts[1] == 'ascend' ? 'descend' : 'ascend'
            }
        }
        this.sortKey = orderkey + "@" + sort;

        this.getExcelDataBySort(orderkey == 'modedatacreatedate' ?
            [{ "orderkey": orderkey, "sortOrder": sort }, { "orderkey": "modedatacreatetime", "sortOrder": sort }]
            : [{ "orderkey": orderkey, "sortOrder": sort }]);
    }


    @action init = (workbook: GC.Spread.Sheets.Workbook) => {
        this.workbook = workbook;
        this.workbook.bind(GC.Spread.Sheets.Events.EditStarting, this.editStarting);
        //    this.workbook.bind(GC.Spread.Sheets.Events.TopRowChanged, this.topRowChanged); 取消上拉刷新
        this.workbook.bind(GC.Spread.Sheets.Events.ValueChanged, this.valueChanged);
        this.workbook.bind(GC.Spread.Sheets.Events.DragFillBlock, this.dragFillBlock);
        this.workbook.bind(GC.Spread.Sheets.Events.DragDropBlock, this.dragDropBlock);
        this.workbook.bind(GC.Spread.Sheets.Events.ColumnWidthChanged, (e, info: GC.Spread.Sheets.IColumnWidthChangedEventArgs) => {
            const { colList, sheet } = info;
            API.columnWidth({
                ...this.params,
                colList: JSON.stringify(colList.map(d => ({
                    col: d,
                    dataIndex: this.backColumn[d].id,
                    width: sheet.getColumnWidth(d)
                })))
            });
        });
        this.workbook.bind(GC.Spread.Sheets.Events.RowHeightChanged, (e, info: GC.Spread.Sheets.IRowHeightChangedEventArgs) => {
            const { sheet, rowList } = info;
            const { row: rowStart } = this.table.dataRange();
            const datas: any[] = this.dataSource.getValue('datas') as any[] || [];
            API.rowHeight({
                ...this.params,
                rowList: JSON.stringify(rowList.map(d => ({
                    row: d,
                    randomFieldId: datas[d - rowStart].randomFieldId,
                    randomFieldSubKeyd_id: datas[d - rowStart].randomFieldSubKeyd_id,
                    height: sheet.getRowHeight(d)
                })))
            })
        })
        this.workbook.bind(GC.Spread.Sheets.Events.LeftColumnChanged, (e, info: GC.Spread.Sheets.ILeftColumnChangedEventArgs) => {
            this.leftCol = info.newLeftCol;
        });

        this.workbook.bind(GC.Spread.Sheets.Events.TopRowChanged, (e, info: GC.Spread.Sheets.ITopRowChangedEventArgs) => {
            this.topRow = info.newTopRow;
        });

        this.dataSource = new GC.Spread.Sheets.Bindings.CellBindingSource({ datas: [] });
        register(this.workbook.commandManager(), this);
        this.contextMenu = ((this.workbook as any).contextMenu as GC.Spread.Sheets.ContextMenu.ContextMenu);
        const onOpenMenu = this.contextMenu.onOpenMenu;
        const that = this;
        this.contextMenu.onOpenMenu = function (menuData, itemsDataForShown, hitInfo, spread) {
            if (that.editable) {
                return onOpenMenu(menuData, itemsDataForShown, hitInfo, spread);
            } else {
                return true;
            }
        }
    }

    getAddedData = () => {
        const dataArray: any[] = [];
        const fieldName: any = {};
        this.backColumn.forEach(col => {
            fieldName[col.id] = col.column;
        })
        each(this.changedValues, (data, key) => {
            const { randomFieldId } = getRandomFieldId(key);
            if (this.insertedRows.indexOf(randomFieldId) > -1 && this.deleteDatas.indexOf(randomFieldId) === -1) {//删除的集合中包括这个id，那么就不保存
                const addData: any = {};
                each(data.new, (value, key) => {
                    addData[fieldName[key]] = value;
                })
                dataArray.push(addData);
            }
        });
        return dataArray;

    }
    getChangedData = () => {
        const dataArray: any[] = [];
        each(this.changedValues, (data, key) => {
            const { randomFieldId, randomFieldSubKeyd_id } = getRandomFieldId(key);
            if (this.insertedRows.indexOf(randomFieldId) === -1) {
                dataArray.push({
                    ...data.new,
                    randomFieldId,
                    randomFieldSubKeyd_id
                });
            }
        })
        return dataArray;
    }
    getChangedOldData = () => {
        const dataArray: any[] = [];
        each(this.changedValues, (data, key) => {
            const { randomFieldId, randomFieldSubKeyd_id } = getRandomFieldId(key);
            if (this.insertedRows.indexOf(randomFieldId) === -1) {
                dataArray.push({
                    ...data.old,
                    randomFieldId,
                    randomFieldSubKeyd_id
                });
            }
        })
        return dataArray;
    }
    @action setChangedValue = (randomFieldId: string, column: IColumns, info: GC.Spread.Sheets.IValueChangedEventArgs) => {
        //    const { typeName } = column;
        const { newValue, oldValue, sheet, col } = info;
        const data = this.changedValues[randomFieldId] || { new: {}, old: {} };
        data.new[column.id] = getInputValue(newValue);
        if (data.old[column.id] === void 0) {
            data.old[column.id] = getInputValue(oldValue) || '';
        }
        if (data.new[column.id] === data.old[column.id]) {
            delete data.new[column.id];
            delete data.old[column.id];
            set(sheet.modifyedValues, `${randomFieldId}.${col}`, false);
        } else {
            set(sheet.modifyedValues, `${randomFieldId}.${col}`, true);
        }
        try {
            if (typeof oldValue === 'string') {
                data.old["row"] = JSON.parse(oldValue).row || info.row;
                data.old["time"] = JSON.parse(oldValue).time || info.time;
            } else {
                data.old["row"] = oldValue.row || info.row;
                data.old["time"] = oldValue.time || info.time;
            }
        } catch (e) {
        }

        this.changedValues[randomFieldId] = data;
    }
    @action checkValue = (col: IColumns, newValue: string, cancel: () => void) => {
        const { typeName } = col;
        let canceled = false;
        let realValue = getInputValue(newValue);
        if (realValue === '' || realValue === null) {//GC.Spread.Sheets.IValueChangedEventArgs 获取到的newValue为空暂时这么处理
            return true;
        }
        if (typeName === FieldTypeName.Text) {
            if (getRealLength(realValue) > col.length) {
                message.error(`长度不能超过${col.length}`);
                canceled = true;
            }
        } else if (typeName === FieldTypeName.Int) {
            if (!judgeValueIsInt(realValue)) {
                message.error(`请录入整数`);
                canceled = true;
            } else if (getRealLength(realValue) > col.length) {
                message.error(`长度不能超过${col.length}`);
                canceled = true;
            }
        } else if (typeName === FieldTypeName.Float || typeName === FieldTypeName.Thousand || typeName === FieldTypeName.Money) {
            if (typeName === FieldTypeName.Thousand) {
                realValue = realValue.replace(/,/g, '');
            }
            if (realValue !== '' && !judgeValueIsNumber(realValue)) {
                message.error(`请录入浮点数`);
                canceled = true;
            } else {
                if (realValue) {
                    const [left, right = ''] = realValue.split('.');

                    if (right.length > col.qfws) {
                        message.error(`小数位数不能超过${col.qfws}`);
                        canceled = true;
                    } else if (left.length > col.length) {
                        message.error(`整数位数不能超过${col.length}`);
                        canceled = true;
                    }
                }

            }

        }
        if (canceled) {
            cancel();
            return false;
        } else {
            return true;
        }

    }
    @action valueChanged = (e: string, info: GC.Spread.Sheets.IValueChangedEventArgs) => {
        if (this.dataSource && this.backColumn && this.table) {
            const { sheet, row, col, newValue } = info;
            let { oldValue } = info
            const column = this.backColumn[col];
            if (this.checkValue(column, newValue, () => {
                sheet.setValue(row, col, oldValue);
            })) {
                const datas = this.dataSource.getValue('datas') as any[];
                const { row: startRow } = this.table.dataRange();
                const data = datas[row - startRow] || {};
                if (column.typeName === FieldTypeName.Select
                    || column.typeName === FieldTypeName.Text
                    || column.typeName === FieldTypeName.Int
                    || column.typeName === FieldTypeName.Float
                    || column.typeName === FieldTypeName.Thousand
                    || column.typeName === FieldTypeName.Money) {
                    data[column.column] = getInputValue(newValue);
                }
                datas[row - startRow] = data;
                try {
                    if (typeof info.oldValue === 'string') {
                        info.oldValue = { ...JSON.parse(info.oldValue), row: row, time: data.time }
                    } else {
                        info.oldValue = { ...info.oldValue, row: row, time: data.time }
                    }
                } catch (e) {
                }

                this.setChangedValue(getRandomId(data), column, info);
            }
        }
    }

    @action
    getExcelDataBySort = (sort) => {
        this.sort = JSON.stringify(sort);
        this.getDatas(this.dataKey, this.current);
    }



    @action getDatas = (dataKey: string, current: number = 1) => {
        this.loading = true;
        this.dataKey = dataKey;
        this.current = current;
        this.hasMore = true;
        if (this.dataSource) {
            this.dataSource.setValue('datas', []);
        }
        const initData = () => {
            if (this.workbook) {
                Promise.all([API.columns(this.params), API.getDataAndTime({ dataKey, current, sortParams: this.sort, ...this.params }), API.getTableCounts({ dataKey })]).then(([columnsResult, dataResult, datacount]) => {
                    this.datas = [];
                    this.current = current;
                    const { data, time, opentype } = dataResult;
                    this.data = data;
                    this.opentype = opentype;
                    listStore.editPagination.current = current;
                    listStore.editPagination.pageSize = data.pageSize;
                    listStore.editPagination.total = datacount.count;
                    listStore.editPagination.onChange = (current: number, pageSize: number) => {
                        listStore.editPagination.pageSize = pageSize || listStore.editPagination.pageSize;
                        this.pageSize = pageSize;
                        try {
                            const dataArray: any[] = [];
                            each(this.changedValues, (data, key) => {
                                const { randomFieldId, randomFieldSubKeyd_id } = getRandomFieldId(key);
                                if (this.insertedRows.indexOf(randomFieldId) === -1) {
                                    dataArray.push({
                                        ...data.new,
                                        randomFieldId,
                                        randomFieldSubKeyd_id
                                    });
                                }
                            })
                            this.newDatas = dataArray;
                            if (this.newDatas.length > 0 || this.insertedRows.length > 0) {
                                Modal.confirm({
                                    title: "当前页的数据还未保存，跳转页数后修改的数据将丢失,是否继续跳转？",
                                    okText: getLabel(382958, '确定'),
                                    cancelText: getLabel(201, '取消'),
                                    onOk: () => {
                                        listStore.editPagination.current = current;
                                        this.getDatas(this.dataKey, current);
                                        this.changedValues = {};
                                        this.insertedRows = [];
                                    },
                                    onCancel: () => {
                                    }
                                });
                                return;
                            } else {
                                listStore.editPagination.current = current;
                                this.getDatas(this.dataKey, current);
                            }
                        } catch (e) { }

                    }
                    listStore.editPagination.onShowSizeChange = (current: number, pageSize: number) => {
                        listStore.editPagination.current = current;
                        listStore.editPagination.pageSize = pageSize || listStore.editPagination.pageSize;
                        this.pageSize = pageSize;

                        API.setTablePageSize({
                            pageSize,
                            dataKey: this.dataKey
                        }).then(action(({ status, errorCode, error, datas }) => {
                            if (status == '1') {
                                this.getDatas(this.dataKey, current);
                            } else {
                                message.error(`[${getLabel(127353, '错误') + errorCode}]:${error}`);
                            }
                        }));



                    }
                    Promise.all([this.setColumns(columnsResult), this.setDatas(data, time), this.getCellColor(data)]).then(this.bingDatas);
                });
            } else {
                setTimeout(() => {
                    initData();
                }, 20);
            }
        }
        initData();
    }
    @action setDatas = (result: IDataResult, time) => {
        return new Promise(resolve => {
            const { datas } = result;
            let tempDatas: any;
            tempDatas = datas.map(data => {
                return { ...data, time: time };
            });
            if (modeList.dataLoadAfterCB && typeof modeList.dataLoadAfterCB == 'function') {
                // @ts-ignore
                tempDatas = modeList.dataLoadAfterCB(toJS(tempDatas), 'excel');
            }
            this.pushDatas(tempDatas);
            if (result.datas.length < this.pageSize) {
                this.hasMore = false;
            }
            API.getRowHeight({
                ...this.params,
                randomIds: JSON.stringify(datas.map(d => ({ randomFieldId: d.randomFieldId, randomFieldSubKeyd_id: d.randomFieldSubKeyd_id })))
            }).then(({ rowHeight = [] }: { rowHeight: IRowHeight[] }) => {
                rowHeight.forEach(rh => {
                    this.rowHeights[getRandomId(rh)] = rh.height;
                });
                this.loading = false;
                resolve();
            })

        });

    }


    @action getCellColor = (result: IDataResult) => {
        return new Promise(resolve => {
            let { datas } = result;
            API.getCellColor({
                ...this.params,
                randomIds: JSON.stringify(datas.map(d => ({ randomFieldId: d.randomFieldId, randomFieldSubKeyd_id: d.randomFieldSubKeyd_id })))
            }).then((dataResult) => {
                const { color, time } = dataResult;
                this.colorData = color;
                this.colortime = time;
                this.loading = false;
                resolve();
            })
        });

    }
    showInfo = (info) => {
        if (info === this.oldInfo) {
            window.clearTimeout(this.clearInfoTimer);
            this.clearInfoTimer = window.setTimeout(() => {
                this.oldInfo = '';
            }, 700);
        } else {
            message.info(info);
            this.oldInfo = info;
        }

    }

    @action editStarting = (e: any, info: GC.Spread.Sheets.IEditStartingEventArgs) => {
        const { row, sheet, col } = info;
        const column = this.backColumn.length > col ? this.backColumn[col] : {} as IColumns;
        if (sheet.tables.find(row, col) && this.editable && column.editable === '1') {
        } else {
            info.cancel = true;
        }
    }
    @action setColumns = (result: IColumnsResult) => {
        return new Promise(resolve => {
            if (result.status === '1') {
                this.siderWidth = result.siderWidth;
                this.pushColumns(result.resultList);
            }
            resolve();
        });
    }

    @action pushDatas = (datas: any[] = []) => {
        const olddatas: any[] = this.dataSource.getValue('datas') as any[];
        const newdatas = uniqBy([...olddatas, ...datas], d => getRandomId(d));
        this.dataSource.setValue('datas', newdatas);
    }

    @action
    setFiexdInfo = (val) => {
        const valArr = val.split(',');
        this.lockrow = valArr[0] || 0;
        this.lockcol = valArr[1] || 0;
    }

    @action pushColumns = (columns: IColumns[]) => {
        this.backColumn = columns.map(d => {
            return {
                ...d,
                length: getTextLength(d),
                qfws: getFloatQfws(d)
            }
        });

        this.workbook.suspendPaint();
        this.workbook.fromJSON({}, false);
        const sheet = this.workbook.getSheet(0);
        (sheet as any).setChangedValue = this.setChangedValue;
        sheet.setColumnCount(columns.length);
        (window as any).table = this.table = sheet.tables.add('表格', 0, 0, 1, columns.length,
            GC.Spread.Sheets.Tables.TableThemes.light11, { showHeader: false, rowFilterVisible: false });
        sheet.modifyedValues = {};
        this.insertedRows = [];
        //  const style= GC.Spread.Sheets.Tables.TableThemes.light11.headerRowStyle();
        const getInt = (value: string, def: number) => {
            if (value) {
                let a = parseInt(value);
                a = isNaN(a) ? def : a;
                return a;
            }
            return def;
        }
        let { lockrow, lockcol } = this.params;
        sheet.frozenRowCount(getInt(lockrow ? lockrow : (this.lockrow != '-1' ? this.lockrow : 0), 0));
        sheet.frozenColumnCount(getInt(lockcol ? lockcol : (this.lockcol != '-1' ? this.lockcol : 0), 0));
        const style: GC.Spread.Sheets.Tables.TableStyle = GC.Spread.Sheets.Tables.TableThemes.light11.headerRowStyle();
        let widths: number[] = [];
        let totalWidth = 0;
        const clientWidth = document.documentElement.clientWidth - sheet.getColumnWidth(0, GC.Spread.Sheets.SheetArea.rowHeader);
        const perWidth = clientWidth / 100;
        this.columns = columns.map((d, index) => {
            let width = parseFloat(d.colwidth);
            if (d.width !== void 0) {
                width = d.width / perWidth;
            }
            totalWidth += width;
            widths.push(width);
            sheet.getCell(0, index, GC.Spread.Sheets.SheetArea.colHeader)
                .font(style.font)
                .foreColor(style.foreColor)
                .backColor(style.backColor)
                .cellType(HeaderCellType(d, this));
            return new GC.Spread.Sheets.Tables.TableColumn(d.id).dataField(d.column + 'span').name(d.text);
        });

        const noneWidths = widths.filter(d => d <= 0);
        let avgwidth = 5;
        if (totalWidth + noneWidths.length * 5 < 100) {
            avgwidth = (100 - totalWidth) / noneWidths.length;
        }

        avgwidth = avgwidth * perWidth;
        widths.forEach((width, index) => {
            sheet.setColumnWidth(index, width <= 0 ? avgwidth : width * perWidth);
        })

        this.table.bindingPath('datas');
        this.table.bindColumns(this.columns);
        this.table.autoGenerateColumns(false);
        // sheet.bindColumns(this.columns);
        this.workbook.resumePaint();
    }
    @action bingDatas = () => {
        this.workbook.suspendPaint();
        this.workbook.sheets.forEach(sheet => {
            sheet.setDataSource(this.dataSource);
        });
        const sheet = this.workbook.getActiveSheet();
        this.table.bindingPath('datas');


        this.backColumn = this.backColumn.map(col => {
            return {
                ...col,
                 title: this.browserMap[col.id] ? this.browserMap[col.id].title : '',
                // asynLoadAll: this.browserMap[col.id] ? this.browserMap[col.id].asynLoadAll : false,
                defaultExpandedLevel: this.browserMap[col.id] ? this.browserMap[col.id].defaultExpandedLevel : 0,
                dataParams: this.browserMap[col.id] ? this.browserMap[col.id].dataParams : {},
                destDataParams: this.browserMap[col.id] ? this.browserMap[col.id].destDataParams : {},
                tabs: this.browserMap[col.id] ? this.browserMap[col.id].tabs : [],
                conditionDataParams: this.browserMap[col.id] ? this.browserMap[col.id].conditionDataParams : {},
                hasAdvanceSerach: this.browserMap[col.id] ? this.browserMap[col.id].hasAdvanceSerach : false,
                scrollx: this.browserMap[col.id] ? this.browserMap[col.id].scrollx : false
            };
        });
        this.backColumn.forEach((col, index) => {
            const cellType = FieldCellType(col, this.editable && col.editable === '1');
            sheet.getRange(row, index, rowCount, 1).cellType(cellType);
            //  sheet.setValue(0,index,"",GC.Spread.Sheets.SheetArea.colHeader);//设置头部列名为空
            this.nameIndex[col.column] = index;  //列名-index
        });

        let id_columnColor = {};
        if (this.colorData) {
            // //获取行号
            for (let index = 0; index < this.colorData.length; index++) {
                const randomFieldId = this.colorData[index].randomFieldId;
                if (id_columnColor[randomFieldId] == null) {
                    let columnColor = {};
                    columnColor[this.colorData[index].fieldname] = this.colorData[index].color;
                    id_columnColor[randomFieldId] = columnColor;
                } else {
                    id_columnColor[randomFieldId][this.colorData[index].fieldname] = this.colorData[index].color;
                }
            }
        }
        const datas: any[] = this.dataSource.getValue('datas') as any[];
        const { row, rowCount, colCount } = this.table.dataRange();
        datas.forEach((d, i) => {
            let height = this.rowHeights[getRandomId(d)] === void 0 ? 30 : this.rowHeights[getRandomId(d)];
            sheet.setRowHeight(i + row, height);
            const id = d.randomFieldId || '';
            const colorMap = id_columnColor[id];
            try {
                for (let j = 0; j < colCount; j++) {//插入行的时候，颜色会自动复制，这里先清除颜色。
                    const cell = this.workbook.getActiveSheet().getCell(i, j);
                    cell.backColor("");
                }
                if (colorMap != null) {
                    each(colorMap, (data, key) => {//data-color  key 列名
                        const col = this.nameIndex[key];
                        if (col != null) {
                            sheet.getRange(i, col, 1, 1).backColor(data);
                        }
                    });
                }
            } catch (error) {
                console && console.log(error)
            }
        });
        sheet.getRange(0, 0, rowCount, colCount).font($('body').css('font')).formatter("@").vAlign(GC.Spread.Sheets.VerticalAlign.center);
        sheet.setRowCount(rowCount);
        sheet.showRow(this.topRow, GC.Spread.Sheets.VerticalPosition.top);
        sheet.showColumn(this.leftCol, GC.Spread.Sheets.HorizontalPosition.left)
        //  sheet.setColumnVisible(0, false, GC.Spread.Sheets.SheetArea.rowHeader);//隐藏行号
        //   sheet.setRowVisible(0, false, GC.Spread.Sheets.SheetArea.colHeader);//隐藏列号
        this.workbook.options.tabStripVisible = false; // 左下角tab页不显示
        this.workbook.resumePaint();
    }
    @action batchEdit = (dataKey: string, dataList: IFieldEditableProps[], browserMap, rightMenus, parm) => {
        this.editable = true;
        const dataMap: any = {};
        dataList.forEach(data => {
            dataMap[data.fieldid] = data;
        });
        this.browserMap = browserMap;
        this.parm = parm;
        this.rightMenus = rightMenus;
        this.backColumn = this.backColumn.map(col => {
            return { ...col, ...dataMap[col.id] };
        });
        this.changedValues = {};
        this.dataKey = dataKey;
        this.getDatas(dataKey, 1);
    }

    @action doBack = (dataKey: string) => {
        this.editable = false;
        this.dataKey = dataKey;
        this.changedValues = {};
        this.insertedRows = [];
        this.getDatas(dataKey, 1);
    }

    @action doBatchStorage = (callback?: any) => {
        if (flag1) {
            return;
        }
        flag1 = true;
        const { customid } = this.params;
        const newDatas = this.getChangedData();
        if (newDatas.length == 0 && this.insertedRows.length == 0) {
            message.warn('未做任何修改！');
            flag1 = false;
            return;
        }
        new Promise((resolve, reject) => {
            ListAPI.batchEditGetVerifyField({ customid }).then(({ status, result }: { status: '0' | '1'; result: IVerifyFieldResult }) => {

                if (result.status === '1') {
                    resolve(result.VerifyField);
                }
                resolve([]);
            }).catch(e => {
                resolve([]);
            });
        }).then((verifyFields: any[]) => {
            if (verifyFields.length === 0) {
                return;
            }

        }).then(() => {
            this.batchEditSave(callback);
        }).catch(error => {
            // console.log(error);
        })
    }
    @action batchEditSave = (callback?) => {
        const oldData = JSON.stringify(this.getChangedOldData());
        let odata = this.getChangedOldData();//旧数据
        let newdata = this.getChangedData();//新数据
        const { customid } = this.params;
        if (odata.length > 0) {//修改
            ListAPI.checkDataIsChange({ customid, oldData }).then((data: any) => {
                if (data.status == "1") {
                    if (data.errMessage) {
                        Modal.confirm({
                            title: '系统提示',
                            width: 400,
                            okText: getLabel(382958, '确定'),
                            cancelText: getLabel(201, '取消'),
                            content: <div dangerouslySetInnerHTML={{ __html: data.errMessage }}></div>,
                            onOk: () => {
                                let trueOldData: any = [];
                                let trueData: any = [];
                                let temp: any = [];
                                for (var i in data.datas) {
                                    temp[data.datas[i].randomFieldId] = true;
                                }
                                for (var k in odata) {
                                    if (!temp[odata[k].randomFieldId]) {
                                        trueOldData.push(odata[k])
                                    }
                                }
                                for (var a in newdata) {
                                    if (!temp[newdata[a].randomFieldId]) {
                                        trueData.push(newdata[a])
                                    }
                                }
                                this.submitData(trueOldData, trueData, callback);
                            },
                            onCancel() { },
                        });
                        flag1 = false;
                    } else {
                        this.submitData(null, null, callback);
                    }
                } else {
                    flag1 = false;
                    message.error("校验数据是否过期出现异常");
                }
            })
        } else {
            this.submitData(null, null, callback);
        }
    }




    submitData = (trueOldData?, trueData?, callback?) => {
        this.loading = true;
        const data = trueData ? JSON.stringify(trueData) : JSON.stringify(this.getChangedData());
        const oldData = trueOldData ? JSON.stringify(trueOldData) : JSON.stringify(this.getChangedOldData());
        const { customid } = this.params;
        Promise.all([saveDatas({
            ...this.params,
            datas: JSON.stringify(this.getAddedData())
        }), ListAPI.batchEditSave({ customid, data, oldData })]).then(([result1, result]) => {
            const { error, status, pageExpendResult } = result as any;
            if (status == '1') {
                if (callback) { callback() }
                this.changedValues = {};
                this.workbook.getActiveSheet().modifyedValues = {};//取消红点
                this.workbook.getActiveSheet().repaint();//重新绘制spread
                this.loading = false;
                message.info(getLabel(83551, '保存成功！'));
                this.getDatas(this.dataKey, this.current);
                if (pageExpendResult && pageExpendResult.haveError) {
                    showExpendError(pageExpendResult, "/spa/cube/index.html#/main/cube/search?customid=" + customid + "&");
                    return;
                }
            } else {
                message.error(error)
                throw error;
            }
            this.loading = false;
            flag1 = false;
        })
    }


    @action
    doCustomAction = (menu: any) => {
        if (menu.function) {
            try {
                const func = eval(`this.${menu.function}`);
                if (typeof func == 'function') {
                    func(menu.key);
                }
            } catch (e) {
                message.error(e);
                throw e;
            }
        }
    }



    windowOpenOnSelf = (expandid: string, billid?: any) => {
        this.secondConfirmPrompt(expandid, () => {
            this.doInterfacesAction(this.billIds, expandid, this.windowOpenOnSelfCallBack, { url: this.parm.urlMap[expandid] });
        })
    }
    windowOpenOnSelfCallBack = ({ url }: any) => {
        if (url) {
            window.location.href = replaceE8Url(url);
        }
    }
    windowOpenOnNew = (expandid: string, billid?: any) => {
        this.secondConfirmPrompt(expandid, () => {
            this.doInterfacesAction(this.billIds, expandid, this.windowOpenOnNewCallBack, { url: this.parm.urlMap[expandid] });
        })
    }
    windowOpenOnNewCallBack = ({ url }: any) => {
        //    this.refresh();
        var width = screen.availWidth - 10;
        var height = screen.availHeight - 50;
        var szFeatures = 'top=0,';
        szFeatures += 'left=0,';
        szFeatures += 'width=' + width + ',';
        szFeatures += 'height=' + height + ',';
        szFeatures += 'directories=no,';
        szFeatures += 'status=yes,toolbar=no,location=no,';
        szFeatures += 'menubar=no,';
        szFeatures += 'scrollbars=yes,';
        szFeatures += 'resizable=yes'; //channelmode
        window.open(replaceE8Url(url), '', szFeatures);
    }
    //页面扩展得方法执行
    doCustomFunction = (expandid: string, _?: any, billid?: any) => {
        this.secondConfirmPrompt(expandid, () => {
            this.doInterfacesAction(this.billIds, expandid, this.doCustomFunctionCallBack, { url: this.parm.urlMap[expandid] });
        });
    }
    doCustomFunctionCallBack = ({ url }: any) => {
        eval(url);
    }
    //二次确认提示
    secondConfirmPrompt = (pageexpandid: string, callBackFun: Function) => {
        const confirmContent = this.parm.confirmMap[pageexpandid];
        if (_.trim(confirmContent)) {   //页面扩展得二次确认提示
            Modal.confirm({
                title: <div dangerouslySetInnerHTML={{ __html: confirmContent }} />,
                okText: getLabel(382958, '继续'),
                cancelText: getLabel(201, '取消'),
                onOk: () => {
                    callBackFun();
                },
                onCancel() {
                },
            });
            return;
        }
        callBackFun();
        return true;
    }



    //执行接口动作
    doInterfacesAction = (CheckedCheckboxIds: any[], pageexpandid: string, callBackFun?: Function, params?: any) => {
        if (CheckedCheckboxIds && CheckedCheckboxIds.length > 0) {
            const modeid = this.parm.modeId;
            const formid = this.parm.formId;
            ListAPI.doInterface({ pageexpandid, CheckedCheckboxIds, modeid, formid, ...this.parm });
        }
        setTimeout(() => {
            if (callBackFun) {
                if (params) {
                    callBackFun(params);
                } else {
                    callBackFun();
                }
            }
        })
    }


    dragFillBlock = (e: any, info: GC.Spread.Sheets.IDragFillBlockEventArgs) => {
        if (!this.loading && this.editable && this.dataSource && this.table) {
            const { fillRange, fillDirection, sheet, sheetName } = info;
            sheet.suspendPaint();
            const { row, col: startCol, rowCount, colCount } = fillRange;
            if (fillDirection === GC.Spread.Sheets.Fill.FillDirection.down) {
                for (let colIndex = 0; colIndex < colCount; colIndex++) {
                    const col = startCol + colIndex;
                    const datas: any[] = this.dataSource.getValue('datas') as any[];
                    const { row: startRow } = this.table.dataRange();
                    const index = row - startRow - 1;
                    const column = this.backColumn[col];
                    if (index > -1 && index < datas.length && column.editable === '1') {
                        const spanKey = `${column.column}span`;
                        const oldData = (datas[index] || {});
                        const value = oldData[column.column];
                        const valueSpan = oldData[spanKey];
                        for (let temp = 1; temp <= rowCount; temp++) {
                            const data = datas[temp + index];
                            const oldValue = data[column.column];
                            const newValue = value;
                            data[column.column] = newValue;
                            data[spanKey] = valueSpan;
                            datas[temp + index] = data;
                            this.setChangedValue(getRandomId(data), column, { sheet, row: row + temp - 1, col, newValue: { value: newValue }, oldValue: { value: oldValue }, sheetName, time: data["time"] });
                        }

                        this.dataSource.setValue('datas', datas);
                    }
                }
            }
            sheet.resumePaint();
        }

        info.cancel = true;
    }
    dragDropBlock = (e: any, info: GC.Spread.Sheets.IDragDropBlockEventArgs) => {
        const { sheet, sheetName, rowCount, colCount, fromRow, fromCol, toRow, toCol } = info;
        if (this.table && this.dataSource && this.editable && fromCol === toCol) {
            const { row: startRow } = this.table.dataRange();
            const row = fromRow - startRow;
            const row1 = toRow - startRow;
            const datas: any[] = this.dataSource.getValue('datas') as any[];
            sheet.suspendPaint();
            for (let colIndex = 0; colIndex < colCount; colIndex++) {
                const col = this.backColumn[fromCol + colIndex];
                if (col.editable === '1') {
                    for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
                        const fromRow = row + rowIndex;
                        const toRow = row1 + rowIndex;
                        const from = `datas.${fromRow}`;
                        const to = `datas.${toRow}`;
                        const tokey = `${to}.${col.column}`;
                        const formKey = `${from}.${col.column}`;
                        const oldValue = this.dataSource.getValue(tokey);
                        const newValue = this.dataSource.getValue(formKey);
                        const fromKeySapn = `${formKey}span`;
                        const todata = datas[toRow];
                        const fromdata = datas[fromRow];
                        const fromRandomFieldId: string = getRandomId(this.dataSource.getValue(from)) as string;
                        const toRandomFieldId: string = getRandomId(this.dataSource.getValue(to)) as string;
                        this.dataSource.setValue(tokey, newValue);
                        this.dataSource.setValue(`${tokey}span`, this.dataSource.getValue(fromKeySapn));
                        this.dataSource.setValue(formKey, '');
                        this.dataSource.setValue(fromKeySapn, '');
                        this.setChangedValue(fromRandomFieldId, col, { sheet, row: fromRow, col: fromCol, oldValue: { value: newValue }, newValue: { value: '' }, sheetName, time: fromdata["time"] });
                        this.setChangedValue(toRandomFieldId, col, { sheet, row: toRow, col: fromCol, newValue: { value: newValue }, oldValue: { value: oldValue }, sheetName, time: todata["time"] });
                    }
                }
            }
            sheet.resumePaint();
        }
        info.cancel = true;
    }
    clipboardPasted = (info) => {
        if (this.editable && this.table && this.dataSource) {
            const { sheetName, fromRanges = [], fromSheet, pastedRanges, clipboardText } = info;
            this.workbook.commandManager().execute({
                autoFitType: GC.Spread.Sheets.AutoFitType.cell,
                cmd: 'cube-paste-data',
                sheet: this.workbook.getSheetFromName(sheetName),
                sourceRange: fromRanges && fromRanges[0],
                sourceSheet: fromSheet,
                cellRange: pastedRanges && pastedRanges[0],
                value: clipboardText,
                table: this.table,
                dataSource: this.dataSource,
                backColumn: this.backColumn,
                setChangedValue: this.setChangedValue
            });
        }
    }
}
